package com.sjm.demo.utils;

import com.alibaba.fastjson.JSON;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest;
import com.dingtalk.api.request.OapiUserGetRequest;
import com.dingtalk.api.request.OapiUserGetUseridByUnionidRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.dingtalk.api.response.OapiUserGetUseridByUnionidResponse;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;

import java.util.HashMap;
import java.util.Map;

@Slf4j
public class DingUtil {

	/**
	 * 发动请求到钉钉获取 token 的url，get方式请求
	 */
	private static final String GET_TOKEN_URL = "https://oapi.dingtalk.com/gettoken";

	private static  final String JJ = "zzz";
	private static final String GET_USERINFO_BYCODE_URL = "https://oapi.dingtalk.com/sns/getuserinfo_bycode";
	private static final String GET_USERID_BYUNIONID_URL = "https://oapi.dingtalk.com/user/getUseridByUnionid";
	private static final String GET_USERINFO_BYUSERID_URL = "https://oapi.dingtalk.com/user/get";

	/**
	 * 钉钉成功返回的消息
	 */
	private static final int SUCCESS_CODE = 0;

	/**
	 *
	 *  用于缓存获取的 access_token
	 *  key 为 appkey
	 *  注：appkey和appsecret在开发者后台创建应用的时候可见
	 *  一个应用对应一个 appkey 和 appsecret
	 */
	private static Map<String,TokenData> map = new HashMap<>();

	/**
	 * 【注意】正常情况下access_token有效期为7200秒，有效期内重复获取返回相同结果，并自动续期。
	 * @param appKey
	 * @param appSecret
	 * @return
	 */
	public static String getToken(String appKey, String appSecret){
		// 当前时间 秒
		long currentTime = System.currentTimeMillis() / 1000;
		TokenData tokenData = map.get(appKey);
		if (tokenData == null) {
			return getAccessToken(appKey,appSecret,currentTime);
			// 若缓存中的token过期，重新获取
		}else if (tokenData.expiresIn < currentTime) {
			return getAccessToken(appKey,appSecret,currentTime);
		} else {
			return tokenData.accessToken;
		}
	}

	private static String getAccessToken(String appKey, String appSecret, long currentTime) {
		try {
			DefaultDingTalkClient client = new DefaultDingTalkClient(GET_TOKEN_URL);
			OapiGettokenRequest request = new OapiGettokenRequest();
			request.setAppkey(appKey);
			request.setAppsecret(appSecret);
			request.setHttpMethod("GET");
			OapiGettokenResponse response = client.execute(request);
			if (response.getErrcode().intValue() != SUCCESS_CODE) {
				log.error("DingTalk error,errorCode:{}  , errmsg:{}",response.getErrcode(),response.getErrmsg());
			}
			String accessToken = response.getAccessToken();
			Long expiresIn = response.getExpiresIn();
			// 过期时间，提前一分钟失效
			TokenData tokenData = new TokenData(accessToken, currentTime + expiresIn - 60);
			// 存入缓存中
			map.put(appKey,tokenData);
			return accessToken;

		} catch (ApiException e) {
			e.printStackTrace();
			log.error("DingTalk error,ApiException--->message: {}",e.getMessage());
		}
		return "";
	}

	public static String getUnionid(String code,String accessKey,String accessSecret) throws ApiException {
		DefaultDingTalkClient client = new DefaultDingTalkClient(GET_USERINFO_BYCODE_URL);
		OapiSnsGetuserinfoBycodeRequest getUnionIdRequest = new OapiSnsGetuserinfoBycodeRequest();
		getUnionIdRequest.setTmpAuthCode(code);
		OapiSnsGetuserinfoBycodeResponse response = client.execute(getUnionIdRequest, accessKey, accessSecret);
		log.info("换取用户简要信息参数{}  返回结果{}", code, JSON.toJSONString(response));
		if (!response.isSuccess()) {
			log.error("临时授权ID换用户简要信息失败:{}", response.getErrmsg());
		}
		return response.getUserInfo().getUnionid();
	}

	public static String getUserInfo(String code,String accessKey,String accessSecret) throws ApiException {
		try {
			DefaultDingTalkClient client = new DefaultDingTalkClient(GET_USERINFO_BYCODE_URL);
			OapiSnsGetuserinfoBycodeRequest getUnionIdRequest = new OapiSnsGetuserinfoBycodeRequest();
			getUnionIdRequest.setTmpAuthCode(code);
			OapiSnsGetuserinfoBycodeResponse response = client.execute(getUnionIdRequest, accessKey, accessSecret);
			log.info("换取用户简要信息参数{}  返回结果{}", code, JSON.toJSONString(response));
			if (!response.isSuccess()) {
				log.error("临时授权ID换用户简要信息失败:{}", response.getErrmsg());
			}
			return JSON.toJSONString(response.getUserInfo());
		}catch (NullPointerException e){
			log.error(e.getMessage());
			return null;
		}
	}


	public static String getUserIdByUnionid(String unionid,String accessToken) throws ApiException {
		DingTalkClient defaultDingTalkClient = new DefaultDingTalkClient(GET_USERID_BYUNIONID_URL);
		OapiUserGetUseridByUnionidRequest getUserIdByUnionIdRequest = new OapiUserGetUseridByUnionidRequest();
		getUserIdByUnionIdRequest.setUnionid(unionid);
		getUserIdByUnionIdRequest.setHttpMethod(HttpMethod.GET.name());
		OapiUserGetUseridByUnionidResponse response = defaultDingTalkClient.execute(getUserIdByUnionIdRequest, accessToken);
		log.info("UnionId 换内部 userId参数{}  返回结果{}", unionid, JSON.toJSONString(response));
		return response.getUserid();
	}

	public static Object getUserInfo(String userId,String token) throws ApiException {
		DingTalkClient clientNew = new DefaultDingTalkClient(GET_USERINFO_BYUSERID_URL);
		OapiUserGetRequest request = new OapiUserGetRequest();
		request.setUserid(userId);
		request.setHttpMethod(HttpMethod.GET.name());
		OapiUserGetResponse userInfo = clientNew.execute(request, token);
		log.info("获取用户信息响应报文:{}", userInfo.getBody());
		return userInfo;
	}

	// 内部类存取临时token
	static class TokenData {
		// token
		private String accessToken;
		// 过期时间
		private Long expiresIn;
		TokenData(String accessToken,Long expiresIn){
			this.accessToken = accessToken;
			this.expiresIn = expiresIn;
		}
	}

}